﻿using DryIoc;
using MaterialDesignThemes.Wpf;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Services.Dialogs; 
using System.Windows; 

namespace WPF.Core
{
    public interface IHostDialogService : IDialogService
    {
        Task<IDialogResult> ShowDialogAsync(string pageName, IDialogParameters parameters = null, string identifier = "Root");
    }

    public interface IHostDialogAware : IDialogAware
    {
        string identifier { get; set; }
    }

    public class HostDialogService : DialogService, IHostDialogService
    {
        private readonly IContainerExtension containerExtension;

        public HostDialogService(IContainerExtension containerExtension)
            : base(containerExtension)
        {
            this.containerExtension = containerExtension;
        }

        public async Task<IDialogResult> ShowDialogAsync(string pageName, IDialogParameters parameters = null, string identifier = "Root")
        {
            var dialogContent = GetDialogContent(pageName, identifier);

            if (!(dialogContent.DataContext is IHostDialogAware vm))
                throw new Exception("");

            var eventHandler = GetDialogOpenedEventHandler(vm, parameters);

            var dialogIsOpen = DialogHost.IsDialogOpen(identifier);
            if (dialogIsOpen) return new DialogResult(ButtonResult.Ignore);

            var dialogResult = await DialogHost.Show(dialogContent, identifier, eventHandler);

            if (dialogResult == null)
                return new DialogResult(ButtonResult.Cancel);

            return (IDialogResult)dialogResult;
        }

        private FrameworkElement GetDialogContent(string name, string identifier = "Root")
        {
            var content = containerExtension.Resolve<object>(name);

            if (!(content is FrameworkElement dialogContent))
                throw new NullReferenceException("");

            if (dialogContent is FrameworkElement view && view.DataContext is null && ViewModelLocator.GetAutoWireViewModel(view) is null)
                ViewModelLocator.SetAutoWireViewModel(view, true);

            if (!(dialogContent.DataContext is IHostDialogAware vm))
                throw new NullReferenceException("");

            vm.identifier = identifier;

            return dialogContent;
        }

        private DialogOpenedEventHandler GetDialogOpenedEventHandler(IHostDialogAware vm, IDialogParameters parameters)
        {
            if (parameters == null) parameters = new DialogParameters();

            DialogOpenedEventHandler eventHandler = async (s, e) =>
            {
                var content = e.Session.Content;
                if (vm is IHostDialogAware aware)
                    aware.OnDialogOpened(parameters);

                e.Session.UpdateContent(content);
            };
            return eventHandler;
        }
        
    }
}
